package tzy.viewpager;

import android.content.Context;
import android.database.DataSetObserver;
import android.graphics.drawable.Drawable;
import android.os.Handler;
import android.os.Message;
import android.os.Parcelable;
import android.support.v4.view.PagerAdapter;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;

import java.lang.ref.WeakReference;
import java.util.List;


public class AutoScrollViewPager extends IndicateViewPager {
    private AutoScrollPagerObserver mObserver;
    //    private AutoScrollRunnable mRunnable = new AutoScrollRunnable();
//    private final AutoScroller mAutoScroller = new AutoScroller();
    private static final long AUTO_SCROLL_INTERVAL = 2000;
    private AutoScrollPagerAdapter mAdapter;

    public AutoScrollViewPager(Context context) {
        this(context, null);
    }

    private final MyHandler mHandler;

    public AutoScrollViewPager(Context context, AttributeSet attrs) {
        super(context, attrs);
        mHandler = new MyHandler(this);
        mObserver = new AutoScrollPagerObserver();
    }


    private static class MyHandler extends Handler {
        final WeakReference<AutoScrollViewPager> mReferences;
        boolean isStarted;
        static final int MSG = 0x01;

        public MyHandler(AutoScrollViewPager view) {
            mReferences = new WeakReference<>(view);
        }


        void startAutoScrollNextPage(boolean timely) {

            stopAutoScroll();
            final PagerAdapter adapter = getAdapter();

            if (adapter != null && adapter instanceof AutoScrollPagerAdapter && adapter.getCount() > 1) {
                if (timely) {
                    sendEmptyMessage(MSG);
                } else {
                    sendEmptyMessageDelayed(MSG, AUTO_SCROLL_INTERVAL);
                }
                isStarted = true;
            }
        }


        void stopAutoScroll() {
            if (isStarted) {
                removeMessages(MSG);
                isStarted = false;
            }
        }


        @Override
        public void handleMessage(Message msg) {
            if (msg.what == MSG) {

                final AutoScrollViewPager p = getView();

                if (isStarted && p != null) {
                    final int count = p.getAdapter() == null ? 0 : p.getAdapter().getCount();

                    if (count > 1) {
                        int next = p.getCurrentItem() + 1;
                        if (next >= count) {
                            next = 0;
                        }
//                    removeCallbacks(this);
                        p.setCurrentItem(next);
                        sendEmptyMessageDelayed(MSG, AUTO_SCROLL_INTERVAL);
                    } else {
                        stopAutoScroll();
                    }
                } else {
                    removeMessages(MSG);
                }

            }

        }

        public AutoScrollViewPager getView() {
            return mReferences.get();
        }

        public PagerAdapter getAdapter() {
            final AutoScrollViewPager p = getView();
            return p == null ? null : p.getAdapter();
        }

    }


    @Override
    public void setAdapter(PagerAdapter adapter) {
        if (mAdapter != null) {
            mHandler.stopAutoScroll();
            mAdapter.unregister();
        }

        if (adapter != null) {
            mAdapter = new AutoScrollPagerAdapter(adapter);
            mAdapter.register();
            mHandler.startAutoScrollNextPage(false);
        } else {
            mAdapter = null;
        }
        super.setAdapter(mAdapter);
    }

    public PagerAdapter getSelfAdapter() {
        return mAdapter == null ? null : mAdapter.adapter;
    }

    @Override
    public int getAdapterCount() {
        return mAdapter == null ? 0 : mAdapter.getRealCount();
    }

    @Override
    public int getAdapterCurrentItem() {
        return mAdapter == null ? -1 : mAdapter.getRealPosition(getCurrentItem());
    }

    private class AutoScrollPagerObserver extends DataSetObserver {

        @Override
        public void onChanged() {
            mAdapter.notifyDataSetChanged();
            mHandler.startAutoScrollNextPage(false);
//            Log.i("@@", "@@onChanged" + getCurrentItem());
        }

        @Override
        public void onInvalidated() {
            mAdapter.notifyDataSetChanged();
            mHandler.startAutoScrollNextPage(false);
//            Log.i("@@", "@@onInvalidated");
        }
    }

    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        switch (ev.getAction() & MotionEvent.ACTION_MASK) {
            case MotionEvent.ACTION_DOWN:
                mHandler.stopAutoScroll();
                break;
            case MotionEvent.ACTION_UP:
            case MotionEvent.ACTION_CANCEL:
                mHandler.startAutoScrollNextPage(false);
                break;
        }


        return super.onInterceptTouchEvent(ev);
    }


    @Override
    public boolean onTouchEvent(MotionEvent ev) {
        switch (ev.getAction() & MotionEvent.ACTION_MASK) {
            case MotionEvent.ACTION_DOWN:
                mHandler.stopAutoScroll();
                break;
            case MotionEvent.ACTION_UP:
            case MotionEvent.ACTION_CANCEL:
                mHandler.startAutoScrollNextPage(false);
                break;
        }


        return super.onTouchEvent(ev);
    }

    final class AutoScroller implements Runnable {
        boolean isStarted;

        @Override
        public void run() {
            Log.i("@@", "@@@@@@@@@@@@@@@:run");


        }

        void startAutoScrollNextPage(boolean timely) {
            Log.i("@@", "@@@@@@@@@@@@@@@:startAutoScrollNextPage");

            stopAutoScroll();
            final PagerAdapter adapter = getAdapter();

            if (adapter != null && adapter instanceof AutoScrollPagerAdapter && adapter.getCount() > 1) {
                if (timely) {
                    post(this);
                } else {
                    postDelayed(this, AUTO_SCROLL_INTERVAL);
                }
                isStarted = true;
            }
        }


        void stopAutoScroll() {
            removeCallbacks(this);
            isStarted = false;
        }


    }


    private class AutoScrollPagerAdapter extends IndicatePagerAdapter<Object> {
        final PagerAdapter adapter;

        void unregister() {
            adapter.unregisterDataSetObserver(mObserver);
        }

        void register() {
            adapter.registerDataSetObserver(mObserver);
        }

        public AutoScrollPagerAdapter(PagerAdapter adapter) {
            super(null);
            this.adapter = adapter;
        }

        public final int getRealCount() {
            return adapter.getCount();
        }

        public final int getRealPosition(int position) {
            final int count = getRealCount();

            return count == 0 ? -1 : position < 0 ? -1 : position % getRealCount();
        }

        @Override
        public int getCount() {
            final int count = getRealCount();
            if (count > 1) {
                return Integer.MAX_VALUE;
            }

            return count;
        }

        @Override
        public Drawable getIndicateResource(Context context) {
            return adapter instanceof IndicatePagerAdapter ? ((IndicatePagerAdapter) adapter).getIndicateResource(context) : null;
        }

        @Override
        public Drawable getUnIndicateResource(Context context) {
            return adapter instanceof IndicatePagerAdapter ? ((IndicatePagerAdapter) adapter).getUnIndicateResource(context) : null;
        }


        @Override
        public void startUpdate(ViewGroup container) {
            adapter.startUpdate(container);
        }

        @Override
        public Object instantiateItem(ViewGroup container, int position) {
            return adapter.instantiateItem(container, getRealPosition(position));
        }

        @Override
        public View getView(ViewGroup container, View convertView, int position) {
            return null;
        }

        @Override
        public void destroyItem(ViewGroup container, int position, Object object) {
            adapter.destroyItem(container, getRealPosition(position), object);
        }

        @Override
        public void setPrimaryItem(ViewGroup container, int position, Object object) {
            adapter.setPrimaryItem(container, getRealPosition(position), object);
        }

        @Override
        public void finishUpdate(ViewGroup container) {
            adapter.finishUpdate(container);
        }


        @Override
        public Parcelable saveState() {
            return adapter.saveState();
        }

        @Override
        public void restoreState(Parcelable state, ClassLoader loader) {
            adapter.restoreState(state, loader);
        }

        @Override
        public int getItemPosition(Object object) {
            return adapter.getItemPosition(object);
        }

        @Override
        public void registerDataSetObserver(DataSetObserver observer) {
            super.registerDataSetObserver(observer);
            adapter.registerDataSetObserver(mObserver);
        }

        @Override
        public void unregisterDataSetObserver(DataSetObserver observer) {
            adapter.unregisterDataSetObserver(mObserver);
            super.unregisterDataSetObserver(observer);
        }


        //        @Override
//        public void notifyDataSetChanged() {
//            adapter.notifyDataSetChanged();
//        }


        @Override
        public CharSequence getPageTitle(int position) {
            return adapter.getPageTitle(getRealPosition(position));
        }

        @Override
        public float getPageWidth(int position) {
            return adapter.getPageWidth(getRealPosition(position));
        }

        @Override
        public boolean isViewFromObject(View view, Object object) {
            return adapter.isViewFromObject(view, object);
        }

        @Override
        public void refreshData(List<Object> data) {
            if (adapter instanceof IndicatePagerAdapter) {
                ((IndicatePagerAdapter) adapter).refreshData(data);
            }
        }
    }


}
